package com.link.base.tencent.corpwx.message.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.link.base.tencent.corpwx.message.model.KeyValueItem;
import com.link.base.tencent.corpwx.message.model.MessageMpNews;
import com.link.base.tencent.corpwx.message.model.MessageNews;
import com.link.base.wechat.basic.util.WxExceptionUtil;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.util.HttpRequestUtil;
import com.link.core.util.StringUtils;
import jodd.util.StringUtil;

import java.util.List;

/**
 * 应用消息工具类
 *
 * @author 欧阳振强
 * @date 2019/1/2
 */
public class AgentMessageUtil {
    /**应用消息发送接口*/
    private static final String AGENT_MESSAGE_API = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";

    /**
     * 应用消息 - 发送文本消息
     * 
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param content 文本消息
     */
    public static JSONObject sendAgentTextMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                              List<String> tagIdList, String agentId, String content) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(content)) {
            throw new BasicServiceException("文本消息不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "text");
        JSONObject textObj = new JSONObject();
        textObj.put("content", content);
        obj.put("text", textObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送图片消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param mediaId 图片媒体文件Id
     */
    public static JSONObject sendAgentImageMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                               List<String> tagIdList, String agentId, String mediaId) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(mediaId)) {
            throw new BasicServiceException("图片媒体文件Id不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "image");
        JSONObject imageObj = new JSONObject();
        imageObj.put("media_id", mediaId);
        obj.put("image", imageObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送语音消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param mediaId 语音文件Id
     */
    public static JSONObject sendAgentVoiceMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                               List<String> tagIdList, String agentId, String mediaId) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(mediaId)) {
            throw new BasicServiceException("语音文件Id不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "voice");
        JSONObject voiceObj = new JSONObject();
        voiceObj.put("media_id", mediaId);
        obj.put("voice", voiceObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送视频消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param mediaId 视频媒体文件Id
     * @param title 视频消息标题
     * @param description 视频消息描述
     */
    public static JSONObject sendAgentVideoMsg(String accessToken, boolean sendAll, List<String> userIdList,
                                               List<String> partyIdList, List<String> tagIdList,
                                               String agentId, String mediaId, String title, String description) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(mediaId)) {
            throw new BasicServiceException("视频媒体文件Id不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "video");
        JSONObject videoObj = new JSONObject();
        videoObj.put("media_id", mediaId);
        videoObj.put("title", title);
        videoObj.put("description", description);
        obj.put("video", videoObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送文件消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param mediaId 文件Id
     */
    public static JSONObject sendAgentFileMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                               List<String> tagIdList, String agentId, String mediaId) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(mediaId)) {
            throw new BasicServiceException("文件Id不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "file");
        JSONObject fileObj = new JSONObject();
        fileObj.put("media_id", mediaId);
        obj.put("file", fileObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送文本卡片消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param title 标题
     * @param description 描述
     * @param msgUrl 点击后跳转的链接
     * @param btnTxt 按钮文字
     */
    public static JSONObject sendAgentTextCardMsg(String accessToken, boolean sendAll, List<String> userIdList,
                                                  List<String> partyIdList, List<String> tagIdList, String agentId,
                                                  String title, String description, String msgUrl, String btnTxt) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(title)) {
            throw new BasicServiceException("标题不能为空！");
        }
        if (StringUtils.isBlank(description)) {
            throw new BasicServiceException("描述不能为空！");
        }
        if (StringUtils.isBlank(msgUrl)) {
            throw new BasicServiceException("点击后跳转的链接不能为空！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "textcard");
        JSONObject textCardObj = new JSONObject();
        textCardObj.put("title", title);
        textCardObj.put("description", description);
        textCardObj.put("url", msgUrl);
        textCardObj.put("btntxt", btnTxt);
        obj.put("textcard", textCardObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送图文消息
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param messageNewsList 图文消息列表
     */
    public static JSONObject sendAgentNewsMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                              List<String> tagIdList, String agentId, List<MessageNews> messageNewsList) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (messageNewsList == null || messageNewsList.size() <= 0) {
            throw new BasicServiceException("请传入图文消息列表！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "news");
        JSONArray articles = new JSONArray();
        for (MessageNews item: messageNewsList) {
            // 返回article
            articles.add(getNewsJSON(item));
        }
        JSONObject newsObj = new JSONObject();
        newsObj.put("articles", articles);
        obj.put("news", newsObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 发送图文消息（mpnews）
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param accessToken 接口凭证
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     * @param messageMpNewsList 图文消息列表(mpnews）
     */
    public static JSONObject sendAgentMpNewsMsg(String accessToken, boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                              List<String> tagIdList, String agentId, List<MessageMpNews> messageMpNewsList) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (messageMpNewsList == null || messageMpNewsList.size() <= 0) {
            throw new BasicServiceException("请传入图文消息列表！");
        }
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        JSONObject obj = getBaseAgentMsgJSON(sendAll, userIdList, partyIdList, tagIdList, agentId);
        obj.put("msgtype", "mpnews");
        JSONArray articles = new JSONArray();
        for (MessageMpNews item: messageMpNewsList) {
            // 返回article
            articles.add(getMpNewsJSON(item));
        }
        JSONObject newsObj = new JSONObject();
        newsObj.put("articles", articles);
        obj.put("mpnews", newsObj);
        String param = obj.toJSONString();
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 应用消息 - 小程序通知消息
     *
     * @author 欧阳振强
     * @date 2020/01/15
     * @param accessToken 接口凭证
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param appId 小程序Id
     * @param page 点击消息卡片后的小程序页面，仅限本小程序内的页面。该字段不填则消息点击后不跳转
     * @param title 消息标题
     * @param description 消息描述
     * @param emphasisFirstItem 是否放大第一个content_item
     * @param contentItems 消息内容键值对，最多允许10个item
     */
    public static JSONObject sendMiniProgramMsg(String accessToken,  List<String> userIdList, List<String> partyIdList,
                                                   List<String> tagIdList, String appId, String page, String title, String description,
                                                   String emphasisFirstItem, List<KeyValueItem> contentItems) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (StringUtils.isBlank(appId)) {
            throw new BasicServiceException("小程序Id不能为空！");
        }
        if (StringUtils.isBlank(title)) {
            throw new BasicServiceException("标题不能为空！");
        }
        JSONObject obj = getBaseMiniProgramMsgJSON(userIdList, partyIdList, tagIdList);
        obj.put("msgtype", "miniprogram_notice");
        JSONObject noticeObj = new JSONObject();
        noticeObj.put("appid", appId);
        noticeObj.put("title", title);
        if (StringUtils.isNotBlank(page)) {
            noticeObj.put("page", page);
        }
        if (StringUtils.isNotBlank(description)) {
            noticeObj.put("description", description);
        }
        if (StringUtils.isNotBlank(emphasisFirstItem)) {
            noticeObj.put("emphasis_first_item", emphasisFirstItem);
        }
        if (contentItems != null) {
            if (contentItems.size() > 10) {
                throw new BasicServiceException("消息内容键值对，最多允许10个item！");
            }
            JSONArray contentItemArray = new JSONArray();
            for (KeyValueItem item: contentItems) {
                JSONObject contentItem = new JSONObject();
                contentItem.put("key", item.getKey());
                contentItem.put("value", item.getValue());
                contentItemArray.add(contentItem);
            }
            noticeObj.put("content_item", contentItemArray);
        }
        obj.put("miniprogram_notice", noticeObj);
        String param = obj.toJSONString();
        String url = AGENT_MESSAGE_API.replace("ACCESS_TOKEN", accessToken);
        String resultStr = HttpRequestUtil.jsonPost(url, param);
        return WxExceptionUtil.parse(resultStr);
    }

    /**
     * 构造基础小程序消息发送JSON对象
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     */
    public static JSONObject getBaseMiniProgramMsgJSON(List<String> userIdList, List<String> partyIdList,
                                                 List<String> tagIdList) throws Exception {
        JSONObject obj = new JSONObject();
        boolean existSendUserFlag = false;
        if (userIdList != null && userIdList.size() > 0) {
            existSendUserFlag = true;
            obj.put("touser", listToString(userIdList));
        }
        if (partyIdList != null && partyIdList.size() > 0) {
            existSendUserFlag = true;
            obj.put("toparty", listToString(partyIdList));
        }
        if (tagIdList != null && tagIdList.size() > 0) {
            existSendUserFlag = true;
            obj.put("totag", listToString(tagIdList));
        }
        if (!existSendUserFlag) {
            throw new BasicServiceException("请维护消息接收对象！");
        }
        return obj;
    }

    /**
     * 构造基础应用消息发送JSON对象
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param sendAll 是否全员发送
     * @param userIdList 消息接收人Id列表
     * @param partyIdList 消息接收部门Id列表
     * @param tagIdList 消息接收标签Id列表
     * @param agentId 应用Id
     */
    public static JSONObject getBaseAgentMsgJSON(boolean sendAll, List<String> userIdList, List<String> partyIdList,
                                                 List<String> tagIdList, String agentId) throws Exception {
        if (StringUtils.isBlank(agentId)) {
            throw new BasicServiceException("应用Id不能为空！");
        }
        JSONObject obj = new JSONObject();
        obj.put("safe", "0");
        obj.put("agentid", agentId);
        if (sendAll) {
            obj.put("touser", "@all");
        } else {
            boolean existSendUserFlag = false;
            if (userIdList != null && userIdList.size() > 0) {
                existSendUserFlag = true;
                obj.put("touser", listToString(userIdList));
            }
            if (partyIdList != null && partyIdList.size() > 0) {
                existSendUserFlag = true;
                obj.put("toparty", listToString(partyIdList));
            }
            if (tagIdList != null && tagIdList.size() > 0) {
                existSendUserFlag = true;
                obj.put("totag", listToString(tagIdList));
            }
            if (!existSendUserFlag) {
                throw new BasicServiceException("请维护消息接收对象！");
            }
        }
        return obj;
    }

    /**
     * 构造和检查图文消息(mpnews)JSON对象
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param record 图文消息(mpnews)实体
     */
    public static JSONObject getMpNewsJSON(MessageMpNews record) throws Exception {
        if (StringUtil.isBlank(record.getTitle())) {
            throw new BasicServiceException("图文消息对象标题不能为空！");
        }
        if (StringUtil.isBlank(record.getThumbMediaId())) {
            throw new BasicServiceException("图文消息缩略图的media_id不能为空！");
        }
        if (StringUtil.isBlank(record.getContent())) {
            throw new BasicServiceException("图文消息的内容不能为空！");
        }
        JSONObject article = new JSONObject();
        article.put("title", record.getTitle());
        article.put("thumb_media_id", record.getThumbMediaId());
        article.put("content", record.getContent());
        if (StringUtils.isNotBlank(record.getAuthor())) {
            article.put("author", record.getAuthor());
        }
        if (StringUtils.isNotBlank(record.getContentSourceUrl())) {
            article.put("content_source_url", record.getContentSourceUrl());
        }
        if (StringUtils.isNotBlank(record.getDigest())) {
            article.put("digest", record.getDigest());
        }
        return article;
    }

    /**
     * 构造和检查图文消息(news)JSON对象
     *
     * @author 欧阳振强
     * @date 2020/01/03
     * @param record 图文消息(news)实体
     */
    public static JSONObject getNewsJSON(MessageNews record) throws Exception {
        if (StringUtil.isBlank(record.getTitle())) {
            throw new BasicServiceException("图文消息对象标题不能为空！");
        }
        if (StringUtil.isBlank(record.getUrl())) {
            throw new BasicServiceException("点击后跳转链接不能为空！");
        }
        JSONObject article = new JSONObject();
        article.put("title", record.getTitle());
        article.put("url", record.getUrl());
        if (StringUtils.isNotBlank(record.getDescription())) {
            article.put("description", record.getDescription());
        }
        if (StringUtils.isNotBlank(record.getPicurl())) {
            article.put("picurl", record.getPicurl());
        }
        return article;
    }

    /**
     * 将List转为连接符"|"String
     *
     * @author 唐健
     * @date 2019/01/15
     * @param stringList 字符串列表
     */
    public static String listToString(List<String> stringList) throws Exception {
        StringBuffer codes = new StringBuffer();
        if (stringList != null && stringList.size() != 0) {
            for (int i = 0; i < stringList.size(); i++) {
                if (stringList.get(i) != null && !"".equals(stringList.get(i))) {
                    codes.append(stringList.get(i) + "|");
                }
            }
        }
        String codeStr = codes.toString();
        if (StringUtils.isNotBlank(codeStr)) {
            codeStr = codeStr.substring(0, codeStr.length() - 1);
        }
        return codeStr;
    }
}
